package com.unionftech.common.common

import android.text.TextUtils
import com.unionftech.baselibrary.base.BaseApplication
import com.unionftech.baselibrary.glide.GlideImagerLoader
import com.unionftech.common.base.IUpdate
import com.unionftech.common.base.mvp.impl.IBaseCallBack
import com.unionftech.common.bean.ResponseResult
import com.unionftech.common.common.bean.BannerImageInfo
import com.unionftech.common.common.bean.BannerPosition
import com.unionftech.common.common.bean.CountryInfo
import com.unionftech.common.common.bean.PhoneRegexInfo
import com.unionftech.common.common.bean.SystemUserInfo
import com.unionftech.common.common.model.CommonModel


class GlobalInfoManager private constructor() {
    private var mPublicKeyStr: String = ""
    private var mCountryInfo: CountryInfo? = null
    private var mSystemUser: SystemUserInfo? = null
    private var mUserToken: String = ""
    private var mAllPhoneRegex: List<PhoneRegexInfo> = emptyList()
    private val mBannerInfoMap = mutableMapOf<BannerPosition, List<BannerImageInfo>>()
    private val mCommonModel by lazy { CommonModel() }
    private val mCallBackSet = HashSet<IUpdate>()
    private val mNotifySet = HashSet<IUpdate>()

    companion object {
        @Volatile
        private var mInstance: GlobalInfoManager? = null

        const val UPDATE_PUBLIC_KEY = 1
        const val UPDATE_COUNTRY_INFO = 2
        const val UPDATE_ALL_PHONE_REGEX = 3
        const val UPDATE_USR_INFO = 4
        const val UPDATE_DEMO_LIST = 5
        const val UPDATE_LIVE_LIST = 6
        const val FINISH_SELF = 7
        const val UPDATE_VERSION_INFO = 8


        @JvmStatic
        fun getInstance() = mInstance ?: synchronized(GlobalInfoManager::class.java) {
            mInstance ?: GlobalInfoManager().also {
                mInstance = it
            }
        }
    }

    /**
     * 初始化用户token
     */
    fun initUserToken(token: String) {
        mUserToken = token
    }

    fun getPublicKeyStr(): String {
        return mPublicKeyStr
    }

    fun getCountryInfo(): CountryInfo? {
        return mCountryInfo
    }

    fun getAllPhoneRegex(): List<PhoneRegexInfo> {
        return mAllPhoneRegex
    }

    fun getSystemUserInfo(): SystemUserInfo? {
        return mSystemUser
    }

    fun getUserToken(): String {
        return mUserToken
    }

    fun update() {
        updatePublicKey()
        updateCountryByIp()
        updateAllCountryPhoneRegex()
    }

    fun updateToken(token: String) {
        mUserToken = token
        updateSystemUserInfo(token)
    }

    fun update(type: Int) {
        when (type) {
            UPDATE_PUBLIC_KEY -> updatePublicKey()
            UPDATE_COUNTRY_INFO -> updateCountryByIp()
            UPDATE_ALL_PHONE_REGEX -> updateAllCountryPhoneRegex()
            UPDATE_USR_INFO -> updateSystemUserInfo(mUserToken)
        }
    }


    fun updateUserInfo(userInfo: SystemUserInfo) {
        mSystemUser = userInfo
    }

    fun putBannerInfo(position: BannerPosition, list: List<BannerImageInfo>) {
        mBannerInfoMap[position] = list
    }

    fun getBannerInfo(position: BannerPosition): List<BannerImageInfo>? {
        return mBannerInfoMap.getOrDefault(position, null)
    }

    fun addListener(update: IUpdate) {
        mCallBackSet.add(update)
        mNotifySet.add(update)
    }

    fun remove(update: IUpdate) {
        mCallBackSet.remove(update)
        mNotifySet.remove(update)
    }

    private fun updateAllCountryPhoneRegex() {
        mCommonModel.getAllCountryPhoneRegex(object :
            IBaseCallBack<ResponseResult<List<PhoneRegexInfo>>> {
            override fun onResponse(response: ResponseResult<List<PhoneRegexInfo>>) {
                if (response.code == ResponseResult.SUCCESS_CODE) {
                    response.data?.also {
                        val list = mutableListOf<PhoneRegexInfo>()
                        list.addAll(it)
                        mAllPhoneRegex = list.toList()
                        notifyListener(it)
                    }
                }
            }

        })
    }

    private fun updateSystemUserInfo(token: String) {
        if (TextUtils.isEmpty(token)) {
            return
        }
        mCommonModel.getOuterUserInfo(token,
            object : IBaseCallBack<ResponseResult<SystemUserInfo>> {
                override fun onResponse(response: ResponseResult<SystemUserInfo>) {
                    if (response.code == ResponseResult.SUCCESS_CODE) {
                        response.data?.also { userInfo ->
                            mSystemUser = userInfo
                            notifyListener(userInfo)
                        }
                    }
                }
            })
    }

    private fun updateCountryByIp() {
        mCommonModel.queryCountryByIp(object : IBaseCallBack<ResponseResult<CountryInfo>> {
            override fun onResponse(response: ResponseResult<CountryInfo>) {
                if (response.code == ResponseResult.SUCCESS_CODE) {
                    response.data?.also {
                        mCountryInfo = it
                        notifyListener(it)
                    }
                }
            }
        })
    }

    private fun updatePublicKey() {
        mCommonModel.getPublicKey(object : IBaseCallBack<ResponseResult<String>> {
            override fun onResponse(response: ResponseResult<String>) {
                if (response.code == ResponseResult.SUCCESS_CODE) {
                    response.data?.also {
                        mPublicKeyStr = it
                        notifyListener(it)
                    }
                }
            }
        })
    }

    fun updateAdImage() {
        mCommonModel.getBannerList(BannerPosition.AD,
            object : IBaseCallBack<ResponseResult<List<BannerImageInfo>>> {
                override fun onResponse(response: ResponseResult<List<BannerImageInfo>>) {
                    if (response.code == ResponseResult.SUCCESS_CODE) {
                        response.data?.also { list ->
                            putBannerInfo(BannerPosition.AD, list)
                            for (info in list) {
                                GlideImagerLoader.preloadImage(
                                    BaseApplication.appContext,
                                    info.imageUrl
                                )
                            }
                        }
                    }
                }
            })
    }

    fun updateIntroductionImage() {
        mCommonModel.getBannerList(BannerPosition.INTRODUCTION,
            object : IBaseCallBack<ResponseResult<List<BannerImageInfo>>> {
                override fun onResponse(response: ResponseResult<List<BannerImageInfo>>) {
                    if (response.code == ResponseResult.SUCCESS_CODE) {
                        response.data?.also { list ->
                            putBannerInfo(BannerPosition.INTRODUCTION, list)
                            for (info in list) {
                                GlideImagerLoader.preloadImage(
                                    BaseApplication.appContext,
                                    info.imageUrl
                                )
                            }
                        }
                    }
                }
            })
    }

    private fun notifyListener(obj: Any) {
        val iterator = mCallBackSet.iterator()
        while (iterator.hasNext()) {
            val iUpdate = iterator.next()
            iUpdate.onUpdate(obj)
        }
    }

    /**
     * 通知刷新
     */
    fun notify(clazz: Class<out IUpdate>, type: Int) {
        val iterator = mNotifySet.iterator()
        while (iterator.hasNext()) {
            val iUpdate = iterator.next()
            if (clazz.isInstance(iUpdate)) {
                iUpdate.onUpdate(type)
            }
        }
    }

    /**
     * 通知更新所有
     */
    fun notifyAll(type: Int) {
        val iterator = mNotifySet.iterator()
        while (iterator.hasNext()) {
            val iUpdate = iterator.next()
            iUpdate.onUpdate(type)
        }
    }
}